import {
  world,
  EquipmentSlot,
  Player,
  ItemStack,
  GameMode,
  Entity,
} from "@minecraft/server";
import { utils } from "../../..";

/**
 * Define a tool tag.
 */
export class WeaponTag {
  constructor(
    /**
     * The weapon tag.
     */
    public tag: string,
    /**
     * Additional options of the weapon.
     */
    public options?: WeaponOptions,
  ) {
    this.listeningDurability();
  }
  /**
   * Automatically consume durability for the tools.
   */
  listeningDurability() {
    world.afterEvents.playerBreakBlock.subscribe((event) => {
      const [PLAYER, ITEM] = [
        event.player,
        utils.getEquipmentItem(event.player),
      ];
      if (
        PLAYER.getGameMode() === GameMode.survival ||
        PLAYER.getGameMode() === GameMode.adventure
      ) {
        if (ITEM?.hasTag(this.tag)) {
          const NEW_ITEM = utils.consumeDurability(ITEM, 2, PLAYER);
          PLAYER?.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM,
          );
          if (NEW_ITEM === undefined && this.options?.destroyedAfterEvents) {
            this.options?.destroyedAfterEvents(PLAYER);
          }
        }
      }
    });
    world.afterEvents.entityHitEntity.subscribe((event) => {
      const [ENTITY, ITEM] = [
        event.damagingEntity,
        utils.getEquipmentItem(event.damagingEntity),
      ];
      if (ENTITY instanceof Player) {
        if (
          ENTITY.getGameMode() === GameMode.survival ||
          ENTITY.getGameMode() === GameMode.adventure
        ) {
          if (ITEM?.hasTag(this.tag)) {
            const NEW_ITEM = utils.consumeDurability(ITEM, 1, ENTITY);
            ENTITY?.getComponent("minecraft:equippable")?.setEquipment(
              EquipmentSlot.Mainhand,
              NEW_ITEM,
            );
            if (NEW_ITEM === undefined && this.options?.destroyedAfterEvents) {
              this.options?.destroyedAfterEvents(ENTITY);
            }
          }
        }
      } else if (ITEM?.hasTag(this.tag)) {
        const NEW_ITEM = utils.consumeDurability(ITEM, 1, ENTITY);
        ENTITY?.getComponent("minecraft:equippable")?.setEquipment(
          EquipmentSlot.Mainhand,
          NEW_ITEM,
        );
        if (NEW_ITEM === undefined && this.options?.destroyedAfterEvents) {
          this.options?.destroyedAfterEvents(ENTITY);
        }
      }
    });
  }
}

/**
 * Define a tool.
 */
export class WeaponItem {
  constructor(
    /**
     * Item of the weapon.
     */
    public item: ItemStack,
    /**
     * Additional options of the weapon.
     */
    public options?: WeaponOptions,
  ) {
    this.listeningDurability();
  }
  /**
   * Automatically consume durability for the tools.
   */
  listeningDurability() {
    world.afterEvents.playerBreakBlock.subscribe((event) => {
      const [PLAYER, ITEM] = [
        event.player,
        utils.getEquipmentItem(event.player),
      ];
      if (
        PLAYER.getGameMode() === GameMode.survival ||
        PLAYER.getGameMode() === GameMode.adventure
      ) {
        if (ITEM?.typeId === this.item.typeId) {
          const NEW_ITEM = utils.consumeDurability(ITEM, 2, PLAYER);
          PLAYER?.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM,
          );
          if (NEW_ITEM === undefined && this.options?.destroyedAfterEvents) {
            this.options?.destroyedAfterEvents(PLAYER);
          }
        }
      }
    });
    world.afterEvents.entityHitEntity.subscribe((event) => {
      const [ENTITY, ITEM] = [
        event.damagingEntity,
        utils.getEquipmentItem(event.damagingEntity),
      ];
      if (ENTITY instanceof Player) {
        if (
          ENTITY.getGameMode() === GameMode.survival ||
          ENTITY.getGameMode() === GameMode.adventure
        ) {
          if (ITEM?.typeId === this.item.typeId) {
            const NEW_ITEM = utils.consumeDurability(ITEM, 1, ENTITY);
            ENTITY?.getComponent("minecraft:equippable")?.setEquipment(
              EquipmentSlot.Mainhand,
              NEW_ITEM,
            );
            if (NEW_ITEM === undefined && this.options?.destroyedAfterEvents) {
              this.options?.destroyedAfterEvents(ENTITY);
            }
          }
        }
      } else if (ITEM?.typeId === this.item.typeId) {
        const NEW_ITEM = utils.consumeDurability(ITEM, 1, ENTITY);
        ENTITY?.getComponent("minecraft:equippable")?.setEquipment(
          EquipmentSlot.Mainhand,
          NEW_ITEM,
        );
        if (NEW_ITEM === undefined && this.options?.destroyedAfterEvents) {
          this.options?.destroyedAfterEvents(ENTITY);
        }
      }
    });
  }
}

/**
 * Type of the weapon.
 */
export enum WeaponType {
  /**
   * Define the weapon is a sword.
   */
  sword,
  /**
   * Define a custom sword.
   */
  custom,
}

export interface WeaponOptions {
  /**
   * Type of the tool.
   */
  type?: WeaponType;
  /**
   * Trigger events when the tool has been destroyed.
   */
  destroyedAfterEvents?: (holder: Entity) => void;
}
